﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TechTree.Stalk.Roots
{
    /// <summary>
    /// Componente responsável por "fabricar" todos os componentes da arquitetura (em tempo de execução).
    /// </summary>
    public class Factory<T>
    {
        #region Constants

        private const string UNITY_CONFIGURATION = "unityConfiguration";

        private const string ERRO_NOME_CLASSE_INVALIDO = "O nome da classe passado é inválido (Classe='{0}').";
        private const string ERRO_CONFIGURACAO_UNITY = "A configuração do Unity não foi encontrada.";
        private const string ERRO_UNITY = "Não foi possível criar o componente a partir do alias '{0}' no Unity.";
        private const string ERRO_CRIACAO_TIPO = "Ocorreu um erro na criação do tipo {0}.";
        private const string ERRO_CRIACAO_INSTANCIA = "Erro ao criar instância.";

        private const string CODIGO_10031 = "10031";
        private const string CODIGO_10032 = "10032";
        private const string CODIGO_10033 = "10033";
        private const string CODIGO_10034 = "10034";
        private const string CODIGO_10035 = "10035";
        private const string CODIGO_10132 = "10132";


        #endregion

        #region Public Methods
        /// <summary>
        /// Cria uma instância baseada no nome da classe.
        /// </summary>
        /// <param name="nomeClasse_">Nome da classe</param>
        /// <returns>Instância da classe</returns>
        public static T CreateInstance(string nomeClasse_)
        {
            Type tipoClasse = null;

            try
            {
                tipoClasse = Type.GetType(nomeClasse_);
            }
            catch
            {
                //throw new ExcecaoArquiteturaConfiguracao(String.Format(ERRO_NOME_CLASSE_INVALIDO, nomeClasse_), CODIGO_10031);
            }
          
          
            T tipo;

            try
            {
                tipo = (T)Activator.CreateInstance(tipoClasse);
            }
            catch (Exception excecao)
            {
                //Log.Escrever(ERRO_CRIACAO_INSTANCIA, string.Format(ERRO_CRIACAO_TIPO, nomeClasse_), Categoria.Execucao, Severidade.Erro, excecao);

                // A excecao ocorrida no create instance é uma excecao de targetinvocation, por este motivo no passada a inner. 
                throw new Exception(string.Format(ERRO_CRIACAO_TIPO, tipoClasse.Name), excecao.InnerException);
            }

            return tipo;
        }
        #endregion
    }
}

